package br.com.felix.dbm.controller;

import java.util.HashMap;
import java.util.Map;

import br.com.felix.dbm.database.Column;
import br.com.felix.dbm.database.DataSize;
import br.com.felix.dbm.database.DataType;
import br.com.felix.dbm.ui.ColumnUi;
import br.com.felix.dbm.ui.ForeignKeyUi;
import br.com.felix.dbm.ui.TableUi;

/**
 * Controller for Column objects. Manages the interaction between model and
 * view.
 * 
 * @TODO: Needs refactor to work with multiple files opened.
 * */
public class ColumnController implements Comparable<ColumnController> {

	/**
	 * Keeps track of all the column controllers.
	 * */
	private static Map<Column, ColumnController> mapControllers = new HashMap<Column, ColumnController>();

	private Column column;
	private ColumnUi columnUi;

	/**
	 * Keeps track of all the views a column has. It may have more than one if
	 * it is a foreign key.
	 * */
	private Map<TableUi, ForeignKeyUi> foreignKeyViews = new HashMap<TableUi, ForeignKeyUi>();

	/**
	 * Reference to the table controller that is parent to this column
	 * controller.
	 * */
	private TableController tableController;



	/**
	 * Instantiates a new Column controller for the column. Adds the column
	 * controller to the map of controllers.
	 * */
	public static ColumnController newInstance(Column column, ColumnUi columnUi, TableController tableController) {
		ColumnController cc = new ColumnController(column, columnUi, tableController);
		mapControllers.put(column, cc);
		return cc;
	}



	/**
	 * Initializes private members.
	 * */
	private ColumnController(Column column, ColumnUi columnUi, TableController tableController) {
		this.column = column;
		this.columnUi = columnUi;
		this.tableController = tableController;
	}



	public void setTablePrefix(String tableColumnPrefix) {
		column.setTablePrefix(tableColumnPrefix);
		updateView();
	}



	/**
	 * Sends a message for all of the column's views to update themselves.
	 * */
	public void updateView() {
		columnUi.updateView(column);
		for (ColumnUi columnUi : foreignKeyViews.values()) {
			columnUi.updateView(column);
		}
	}



	public void setName(String text) {
		column.setName(text);
	}



	public void setType(DataType selectedDataType) {
		column.setType(selectedDataType);
	}



	public void setSize(DataSize dataSize) {
		column.setSize(dataSize);
	}



	/**
	 * If a column is set primary key, than it also won't allow nulls.
	 * */
	public void setPrimaryKey(boolean isPrimaryKey) {
		column.setPrimaryKey(isPrimaryKey);
		if (isPrimaryKey) {
			allowNull(false);
		}
	}



	public ColumnUi getView() {
		return columnUi;
	}



	/**
	 * @param tableUi is the table where this is column is a foreign key.
	 * @return the ColumnUi that renders this column as a foreign key.
	 * */
	public ColumnUi getViewForTable(TableUi tableUi) {
		ColumnUi columnUiForTable = foreignKeyViews.get(tableUi);
		if(columnUiForTable==null){
			if(tableController.getView().equals(tableUi)){
				columnUiForTable = columnUi;
			}
		}
		return columnUiForTable;
	}



	/**
	 * @param column the column for which you need the controller.
	 * @return the columnController for the specified column.
	 * */
	public static ColumnController getInstance(Column column) {
		return mapControllers.get(column);
	}



	/**
	 * Adds a foreign key Ui for the specified table.
	 * */
	public void addViewForTable(TableUi tableUi, ForeignKeyUi columnUi) {
		foreignKeyViews.put(tableUi, columnUi);
	}



	@Override
	public int compareTo(ColumnController o) {
		return this.column.compareTo(o.column);
	}



	public Column getModel() {
		return this.column;
	}



	public void allowNull(boolean columnIsNullable) {
		column.allowNull(columnIsNullable);
	}



	/**
	 * Causes this column to be deleted from the entire data model. Which
	 * includes all the associated foreign keys, if any.
	 * */
	public void delete() {
		DataModelController dmc = tableController.getDataModelController();
		dmc.deleteColumn(column);
	}



	public TableController getTableController() {
		return tableController;
	}
	
	
	public static void clear(){
		mapControllers.clear();
	}
}
